#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>           // 时间相关函数
#include <unistd.h>         // UNIX 标准函数
#include <sqlite3.h>        // SQLite 数据库操作
#include <arpa/inet.h>      // 网络地址转换
#include <sys/socket.h>     // 套接字编程
#include <errno.h>          // 错误处理
#include <fcntl.h>          // 文件操作，如 open, O_RDONLY
#include <netinet/in.h>     // 网络地址结构
#include <signal.h>         // 信号处理
#include <dirent.h>         // 目录操作，如 opendir, readdir, closedir
#include <netinet/tcp.h>    // TCP 相关定义
#include <getopt.h>         // 命令行选项解析

#define MAX_BUFFER 512                    // 定义最大缓冲区大小
#define DEVICE_FILE "/sys/bus/w1/devices/28-041701d839ff/w1_slave" // DS18B20 传感器文件路径（请根据实际情况修改）
#define BUFFER_SIZE 1024

// 函数声明
float read_temperature();
void send_cached_data(sqlite3 *db, int sock);
void create_table_if_not_exists(sqlite3 *db);
void store_in_sqlite(sqlite3 *db, const char *data);
int connect_to_server(const char *server_ip, int server_port);
int send_data(int sock, const char *data);
int check_connection(int sock);
int has_cached_data(sqlite3 *db);

// 信号处理函数，忽略 SIGPIPE 信号
void handle_sigpipe(int sig)
{
    printf("收到 SIGPIPE 信号，连接可能已断开。\n");
}

int main(int argc, char *argv[])
{
    char data[MAX_BUFFER];                  // 用于存储设备数据的缓冲区
    char *server_ip = NULL;                 // 服务器IP地址
    int server_port = -1;                   // 服务器端口号
    int interval_seconds = -1;               // 采样间隔时间

    // 命令行参数解析
    int opt;
connect_to_server    while ((opt = getopt(argc, argv, "i:p:s:")) != -1) {
        switch (opt) {
            case 'i':
                server_ip = optarg; // 获取服务器IP地址
                break;
            case 'p':
                server_port = atoi(optarg); // 获取服务器端口号
                break;
            case 's':
                interval_seconds = atoi(optarg); // 获取采样间隔时间
                break;
            default:
                fprintf(stderr, "用法: %s -i <服务器IP> -p <服务器端口> -s <采样间隔>\n", argv[0]);
                exit(EXIT_FAILURE);
        }
    }

    // 检查必需的参数是否提供
    if (server_ip == NULL || server_port == -1 || interval_seconds == -1) {
        fprintf(stderr, "错误: 必须提供服务器IP、服务器端口和采样间隔。\n");
	fprintf(stderr, "用法: %s -i <服务器IP> -p <服务器端口> -s <采样间隔>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打印配置信息
    printf("Hostname: %s\n", server_ip);
    printf("Port: %d\n", server_port);
    printf("Interval (seconds): %d\n", interval_seconds);
    printf("Station ID: weather_station\n");

    sqlite3 *db;  // SQLite 数据库指针
    int rc;       // 返回码

    // 服务器连接标志位和套接字描述符
    int server_connected = 0;  // 服务器连接状态标志，0表示未连接，1表示已连接
    int sock = -1;             // 套接字描述符

    // 捕获并忽略 SIGPIPE 信号，防止向已关闭的套接字写入时程序崩溃
    signal(SIGPIPE, SIG_IGN);

    // 打开 SQLite 数据库
    rc = sqlite3_open("temperature_data.db", &db);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "无法打开 SQLite 数据库: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    // 检查并创建表
    create_table_if_not_exists(db);
    printf("SQLite 表已就绪。\n");

    // 尝试连接服务器
    sock = connect_to_server(server_ip, server_port);

    // 检查连接状态
    if (sock >= 0)
    {
        if (check_connection(sock))
        {
            server_connected = 1;  // 设置服务器连接标志位为1
            printf("成功连接并验证服务器连接状态。\n");
        }
        else
        {
            server_connected = 0;
            printf("无法验证服务器连接状态，进入离线模式。\n");
            close(sock);
            sock = -1;
        }
    }
    else
    {
        server_connected = 0;
        printf("无法连接到服务器，进入离线模式。\n");
    }

    // 设置初始的上次记录时间为当前时间
    time_t last_recorded_time = time(NULL);

    // 主循环
    while (1)
    {
        // 获取当前时间
        time_t current_time = time(NULL);

        // 在主循环中处理数据发送逻辑
        if (!server_connected)
        {
            sock = connect_to_server(server_ip, server_port);
            if (sock >= 0 && check_connection(sock))
            {
                server_connected = 1;
                printf("重新连接并验证服务器连接状态成功。\n");
            }
            else
            {
                server_connected = 0;
                printf("仍然无法连接到服务器。\n");
                if (sock >= 0)
                {
                    close(sock); // 关闭套接字
                    sock = -1;
                }
            }
        }
        else
        {
            if (!check_connection(sock))
            {
                server_connected = 0;
                close(sock); // 关闭套接字
                sock = -1;
            }
            else
            {
                printf("不需要连接\n");
            }
        }

        if (server_connected && has_cached_data(db))
        {
            send_cached_data(db, sock);
        }

        // 在主循环中处理数据发送逻辑
        if (difftime(current_time, last_recorded_time) >= interval_seconds)
        {
            printf("\n在 %s 采集数据", ctime(&current_time));
            memset(data, 0, sizeof(data));
            float temp = read_temperature();

            if (temp != -1)
            {
                char time_str[MAX_BUFFER];
                strftime(time_str, MAX_BUFFER, "%Y-%m-%d %H:%M:%S", localtime(&current_time));
                sprintf(data, "Station ID: weather_station\nTemp: %.2f°C\nTime: %s\n", temp, time_str);
	//	snprintf(data, sizeof(data), "Station ID: weather_station\nTemp: %.2f°C\nTime: %s\n", temp, time_str);

                printf("采集到的数据：\n%s\n", data);
                if (server_connected)
                {
                    if (send_data(sock, data) == -1)
                    {
                        server_connected = 0;
                        close(sock);
                        sock = -1;
                        printf("发送数据失败，进入离线模式。\n");
                        store_in_sqlite(db, data);
                        printf("数据已缓存到本地。\n");
                    }
                    else
                    {
                        printf("数据已发送到服务器。\n");
                    }
                }
                else
                {
                    store_in_sqlite(db, data);
                    printf("数据已缓存到本地。\n");
                }
            }
            else
            {
                printf("读取温度数据失败。\n");
            }

            last_recorded_time = current_time;
        }

        // 休眠一段时间，防止忙等待
        sleep(1);
    }

    // 关闭 SQLite 数据库（实际上不会到达这里）
    sqlite3_close(db);
    return 0;
} 


/*
// 检查服务器连接状态的函数，使用 getsockopt
int check_connection(int sock)
{
    int error = 0;
    socklen_t len = sizeof(error);

    // 获取套接字错误状态
    if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
    {
        printf("getsockopt() 错误: %s\n", strerror(errno));
        return 0;
    }

    if (error != 0)
    {
        // 套接字有错误，连接可能已断开
        printf("套接字错误: %s\n", strerror(error));
        return 0;
    }

    // 连接正常
    return 1;
}*/

// 检查服务器连接状态的函数
//函数
int check_connection(int sock)
{
	struct tcp_info info;
	
	if (sock <= 0)
    {
        return 0;
    }
		
	int len = sizeof(info);
	getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *) & len);
	if ((info.tcpi_state == 1)) 
	{
		printf("服务器已经连接\n");
		return 1;
	} 
    else 
    {
		printf("服务器已经断开\n");
		return 0;
	}
}



// 检查是否有缓存数据的函数
int has_cached_data(sqlite3 *db)
{
    sqlite3_stmt *stmt;
    const char *sql = "SELECT COUNT(*) FROM temperature_logs;";
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "无法准备查询语句: %s\n", sqlite3_errmsg(db));
        return 0;
    }

    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW)
    {
        int count = sqlite3_column_int(stmt, 0);
        sqlite3_finalize(stmt);
        return count > 0 ? 1 : 0;
    }
    else
    {
        fprintf(stderr, "无法执行查询语句: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return 0;
    }
}

// 读取 DS18B20 传感器的温度
float read_temperature()
{
    int fd = -1;
    char buf[128];
    char *ptr = NULL;
    float temp = 0.0;

    // 使用固定的设备文件路径
    const char *device_file = DEVICE_FILE;

    // 打开设备文件
    fd = open(device_file, O_RDONLY);
    if (fd < 0)
    {
        printf("无法打开文件 %s: %s\n", device_file, strerror(errno));
        return -1;
    }

    // 清空缓冲区
    memset(buf, 0, sizeof(buf));

    // 读取文件内容
    if (read(fd, buf, sizeof(buf) - 1) < 0)
    {
        printf("读取数据失败: %s\n", strerror(errno));
        close(fd);
        return -1;
    }

    printf("buf: %s\n", buf);

    // 查找温度数据
    ptr = strstr(buf, "t=");
    if (!ptr)
    {
        printf("无法找到 't=' 字符串。\n");
        close(fd);
        return -1;
    }

    ptr += 2; // 移动指针到温度值
    printf("ptr: %s\n", ptr);

    temp = atof(ptr) / 1000.0; // 转换为摄氏度
    printf("温度: %.2f°C\n", temp);

    close(fd); // 关闭文件

    return temp;
}

// 发送数据到服务器
int send_data(int sock, const char *data) // <<<<< 修改部分：返回类型改为int
{
    ssize_t bytes_sent = send(sock, data, strlen(data), 0);
    if (bytes_sent < 0)
    {
        if (errno == EPIPE || errno == ECONNRESET)
        {
            fprintf(stderr, "发送数据错误: %s\n", strerror(errno));
            return -1; // <<<<< 修改部分：返回错误状态
        }
        else
        {
            fprintf(stderr, "发送数据错误: %s\n", strerror(errno));
            return -1; // <<<<< 修改部分：返回错误状态
        }
    }
    else
    {
        printf("已发送 %zd 字节的数据。\n", bytes_sent);
        return 0; // <<<<< 修改部分：返回成功状态
    }
}

/*
// 发送数据到服务器
int send_data(int sock, const char *data)
{
    ssize_t bytes_sent = send(sock, data, strlen(data), 0);
    if (bytes_sent < 0)
    {
        fprintf(stderr, "发送数据错误: %s\n", strerror(errno));
        return -1; // 发送失败，返回错误状态
    }
    else
    {
        printf("已发送 %zd 字节的数据。\n", bytes_sent);
        return 0; // 发送成功
    }
}
*/

// 连接到服务器
int connect_to_server(const char *server_ip, int server_port)
{
    int conn_fd;
    struct sockaddr_in serv_addr;

    // 创建套接字
    conn_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (conn_fd < 0)
    {
        printf("创建socket失败: %s\n", strerror(errno));
        return -1;
    }

    // 设置服务器地址
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(server_port);

    // 转换 IP 地址
    if (inet_aton(server_ip, &serv_addr.sin_addr) == 0)
    {
        printf("无效的 IP 地址: %s\n", server_ip);
        close(conn_fd);
        return -1;
    }

    // 尝试连接到服务器（阻塞调用）
    if (connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("连接到服务器 [%s:%d] 失败: %s\n", server_ip, server_port, strerror(errno));
        close(conn_fd);
        return -1;
    }

    return conn_fd;
}

// 发送缓存的 SQLite 数据到服务器（每次发送一条）
void send_cached_data(sqlite3 *db, int sock)
{
    sqlite3_stmt *stmt;
    const char *sql = "SELECT id, data FROM temperature_logs ORDER BY id ASC LIMIT 1"; // 每次发送一条历史数据
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);

    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "无法检索缓存的数据: %s\n", sqlite3_errmsg(db));
        return;
    }

    // 检查是否有记录
    if (sqlite3_step(stmt) == SQLITE_ROW)
    {
        int id = sqlite3_column_int(stmt, 0);
        const char *cached_data = (const char*)sqlite3_column_text(stmt, 1);

        printf("发送缓存的数据 ID %d: %s\n", id, cached_data);

        // 发送数据到服务器
        ssize_t bytes_sent = send(sock, cached_data, strlen(cached_data), 0);
        if (bytes_sent < 0)
        {
            fprintf(stderr, "发送缓存的数据错误: %s\n", strerror(errno));
        }
        else
        {
            // 发送成功后删除该记录
            char delete_sql[128];
            snprintf(delete_sql, sizeof(delete_sql), "DELETE FROM temperature_logs WHERE id=%d", id);
            rc = sqlite3_exec(db, delete_sql, 0, 0, NULL);
            if (rc != SQLITE_OK)
            {
                fprintf(stderr, "删除缓存的数据 ID %d 失败: %s\n", id, sqlite3_errmsg(db));
            }
            else
            {
                printf("已删除缓存的数据 ID %d。\n", id);
            }
        }
    }
    else
    {
        // 没有缓存的历史数据需要发送
        // printf("没有缓存的历史数据需要发送。\n"); // 可选：如果不想每次都打印这句话，可以注释掉
    }

    sqlite3_finalize(stmt);
}

// 将数据存储到 SQLite 数据库
void store_in_sqlite(sqlite3 *db, const char *data)
{
   // char *err_msg = 0;
    const char *insert_sql = "INSERT INTO temperature_logs(data) VALUES(?);";
    sqlite3_stmt *stmt;

    // 准备插入语句
    int rc = sqlite3_prepare_v2(db, insert_sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "无法准备插入语句: %s\n", sqlite3_errmsg(db));
        return;
    }

    // 绑定参数
    sqlite3_bind_text(stmt, 1, data, -1, SQLITE_STATIC);

    // 执行插入
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE)
    {
        fprintf(stderr, "无法插入数据: %s\n", sqlite3_errmsg(db));
    }
    else
    {
        // 数据插入成功
        // printf("数据已缓存到 SQLite。\n"); // 可选：减少日志输出
    }

    sqlite3_finalize(stmt);
}

// 创建 SQLite 数据库中的表（如果不存在）
void create_table_if_not_exists(sqlite3 *db)
{
    char *err_msg = 0;
    char *sql = "CREATE TABLE IF NOT EXISTS temperature_logs ("
                "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                "data TEXT);";

    // 执行 SQL 语句
    int rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
    if (rc != SQLITE_OK)
    {
        fprintf(stderr, "无法创建表: %s\n", err_msg);
        sqlite3_free(err_msg);
    }
    else
    {
        // 表创建成功或已存在
        // printf("表已创建或已存在。\n"); // 可选：减少日志输出
    }
}





